package edu.bu.cs673.superkids123.test;

import java.util.List;
import java.util.Iterator;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

import edu.bu.cs673.superkids123.HibernateUtil;
import edu.bu.cs673.superkids123.children.DataObjectAccess.LessonGameManager;
import edu.bu.cs673.superkids123.children.model.CompletedGame;
import edu.bu.cs673.superkids123.children.model.CompletedLesson;
import edu.bu.cs673.superkids123.children.model.Game;
import edu.bu.cs673.superkids123.children.model.Lesson;
import edu.bu.cs673.superkids123.children.model.Level;
import edu.bu.cs673.superkids123.children.model.resources.AchievementFactory;
import edu.bu.cs673.superkids123.children.model.resources.ChildrenResource;
import edu.bu.cs673.superkids123.common.model.Child;
import edu.bu.cs673.superkids123.common.model.Parent;
import edu.bu.cs673.superkids123.common.model.User;
import edu.bu.cs673.superkids123.parents.DataObjectAccess.AchievementManager;
import edu.bu.cs673.superkids123.parents.DataObjectAccess.ParentSystemManager;
import edu.bu.cs673.superkids123.parents.model.Image;
import edu.bu.cs673.superkids123.parents.view.ReportView.GameTableModel;
import edu.bu.cs673.superkids123.common.model.Achievement;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

public class SuperKids123PrepDatabase extends TestCase {

	/**
	 * Create the test case
	 *
	 * @param testName
	 *            name of the test case
	 */
	public SuperKids123PrepDatabase(String testName) {
		super(testName);
	}

	/**
	 * @return the suite of tests being tested
	 */
	public static Test suite() {
		return new TestSuite(SuperKids123PrepDatabase.class);
	}

	/**
	 * Drop everything in the database, and then populate it with default data.
	 */
	@SuppressWarnings("unchecked")
	public void testPrepDatabase() {
		Transaction tx = null;
		Session session = HibernateUtil.getSessionFactory().openSession();
		Query query = null;

		try {
			tx = session.beginTransaction();

			// Remove all children
			query = session.createQuery("From Child");
			List<Child> children = (List<Child>) query.list();
			Iterator<Child> childIt = children.iterator();
			while (childIt.hasNext()) {
				session.delete(childIt.next());
			}
			query = session.createQuery("From Child");
			children = (List<Child>) query.list();
			assertTrue(children.size() == 0);

			// Remove all images
			query = session.createQuery("From Image");
			List<Image> images = (List<Image>) query.list();
			Iterator<Image> imageIt = images.iterator();
			while (imageIt.hasNext()) {
				session.delete(imageIt.next());
			}
			query = session.createQuery("From Image");
			images = (List<Image>) query.list();
			assertTrue(images.size() == 0);

			// Remove all Achievements
			query = session.createQuery("From Achievement");
			List<Achievement> achievs = (List<Achievement>) query.list();
			Iterator<Achievement> achievIt = achievs.iterator();
			while (achievIt.hasNext()) {
				session.delete(achievIt.next());
			}
			query = session.createQuery("From Achievement");
			achievs = (List<Achievement>) query.list();
			assertTrue(achievs.size() == 0);

			// Remove all Parents
			query = session.createQuery("From Parent");
			List<Parent> parents = (List<Parent>) query.list();
			Iterator<Parent> parentIt = parents.iterator();
			while (parentIt.hasNext()) {
				session.delete(parentIt.next());
			}
			query = session.createQuery("From Parent");
			parents = (List<Parent>) query.list();
			assertTrue(parents.size() == 0);

			// Remove all Users
			query = session.createQuery("From User");
			List<User> users = (List<User>) query.list();
			Iterator<User> userIt = users.iterator();
			while (userIt.hasNext()) {
				session.delete(userIt.next());
			}
			query = session.createQuery("From User");
			users = (List<User>) query.list();
			assertTrue(users.size() == 0);

			// Remove all Lessons
			query = session.createQuery("From Lesson");
			List<Lesson> lessons = (List<Lesson>) query.list();
			Iterator<Lesson> lessonIt = lessons.iterator();
			while (lessonIt.hasNext()) {
				session.delete(lessonIt.next());
			}
			query = session.createQuery("From Lesson");
			lessons = (List<Lesson>) query.list();
			assertTrue(lessons.size() == 0);

			// Remove all Games
			query = session.createQuery("From Game");
			List<Game> games = (List<Game>) query.list();
			Iterator<Game> gameIt = games.iterator();
			while (gameIt.hasNext()) {
				session.delete(gameIt.next());
			}
			query = session.createQuery("From Game");
			games = (List<Game>) query.list();
			assertTrue(games.size() == 0);

			// Remove all Levels
			query = session.createQuery("From Level");
			List<Level> levels = (List<Level>) query.list();
			Iterator<Level> levelIt = levels.iterator();
			while (levelIt.hasNext()) {
				session.delete(levelIt.next());
			}
			query = session.createQuery("From Level");
			levels = (List<Level>) query.list();
			assertTrue(levels.size() == 0);

			// Remove all CompletedGames
			query = session.createQuery("From CompletedGame");
			List<CompletedGame> completedGames = (List<CompletedGame>) query.list();
			Iterator<CompletedGame> completedGamesIt = completedGames.iterator();
			while (completedGamesIt.hasNext()) {
				session.delete(completedGamesIt.next());
			}
			query = session.createQuery("From CompletedGame");
			completedGames = (List<CompletedGame>) query.list();
			assertTrue(completedGames.size() == 0);

			// Remove all CompletedLessons
			query = session.createQuery("From CompletedLesson");
			List<CompletedLesson> completedLessons = (List<CompletedLesson>) query.list();
			Iterator<CompletedLesson> completedLessonsIt = completedLessons.iterator();
			while (completedLessonsIt.hasNext()) {
				session.delete(completedLessonsIt.next());
			}
			query = session.createQuery("From CompletedLesson");
			completedLessons = (List<CompletedLesson>) query.list();
			assertTrue(completedLessons.size() == 0);

/*
TODO remove the other tables when used.
edu.bu.cs673.superkids123.common.model.EventLog
edu.bu.cs673.superkids123.common.model.Roles
edu.bu.cs673.superkids123.children.model.Activity
edu.bu.cs673.superkids123.children.model.Answer
edu.bu.cs673.superkids123.children.model.Question
edu.bu.cs673.superkids123.parents.model.ActivityType
edu.bu.cs673.superkids123.parents.model.Color
edu.bu.cs673.superkids123.parents.model.Number
edu.bu.cs673.superkids123.parents.model.Sound
edu.bu.cs673.superkids123.parents.model.SystemTheme
 */
			session.getTransaction().commit();
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}

		// Populate child avatars.
		ParentSystemManager.addImage("boyAvatar0", ChildrenResource.imageBoy);
		ParentSystemManager.addImage("girlAvatar0", ChildrenResource.imageGirlCat);
		ParentSystemManager.addImage("girlAvatar1", ChildrenResource.imageGirlHorn);
		ParentSystemManager.addImage("girlAvatar2", ChildrenResource.imageGirlPink);
		ParentSystemManager.addImage("girlAvatar3", ChildrenResource.imageGirlPrincess);

		// Populate achievements
		AchievementFactory af = new AchievementFactory();
		for (Achievement achievement : af.getAchievementsFromXML()) {
			AchievementManager.addAchievement(achievement);
		}

		// Populate Lessons and Games
		Level level = new Level("Beginner", "A good place to start", 1, 5);
		LessonGameManager.addLevel(level);
		LessonGameManager.addLesson("Lesson: Count", "Follow along and count with me", true, level);
		LessonGameManager.addLesson("Lesson: Add", "See how you can combine numbers to make bigger numbers", true, level);
		LessonGameManager.addGame("Game: Matching", "Count and match the numbers",true, level);
		LessonGameManager.addGame("Game: Math", "Add your way to victory",true, level);
		LessonGameManager.addGame("Game: Archery", "Test your math as well as your aim",true, level);
		LessonGameManager.addGame("Game: Click", "Click your way to victory",true, level);
		LessonGameManager.addGame("Game: Subtraction", "See how you can subtract numbers to make smaller numbers", true, level);
	}
}
